package com.ruoyi.syf.service.impl;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.annotation.ConvertField;
import com.ruoyi.common.annotation.ConvertFieldItem;
import com.ruoyi.common.enums.ConvertType;
import com.ruoyi.syf.domain.RiskCheckTask;
import com.ruoyi.syf.domain.vo.RiskCheckTaskVo;
import com.ruoyi.syf.mapper.RiskCheckTaskMapper;
import com.ruoyi.syf.service.IRiskCheckRecordService;
import com.ruoyi.syf.service.IRiskCheckTaskService;
import com.ruoyi.syf.handler.task.TaskFactory;
import com.ruoyi.syf.task.enttity.ScheduleSetting;
import com.ruoyi.syf.task.service.ScheduleSettingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 排查定时任务Service业务层处理
 *
 * @author yr
 * @date 2024-07-31
 */
@Service
public class RiskCheckTaskServiceImpl extends ServiceImpl<RiskCheckTaskMapper, RiskCheckTask> implements IRiskCheckTaskService {
    @Autowired
    private RiskCheckTaskMapper riskCheckTaskMapper;
    @Autowired
    private ScheduleSettingService scheduleSettingService;
    @Autowired
    private IRiskCheckRecordService checkRecordService;
    @Autowired
    private TaskFactory taskFactory;

    @ConvertField({
            @ConvertFieldItem(fieldName = "checkByDept", assistFieldName = "checkByDeptName", type = ConvertType.DEPT),
            @ConvertFieldItem(fieldName = "taskType", dictType = "task_type", type = ConvertType.DICT)
    })
    @Override
    public List<RiskCheckTaskVo> list(RiskCheckTask riskCheckTask) {
        return riskCheckTaskMapper.list(riskCheckTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addOrUpdateTask(RiskCheckTaskVo vo) throws IllegalAccessException {
        //检查人编码
        List<Long> checkByCodeList = vo.getCheckByList();
        String checkBys = JSON.toJSONString(checkByCodeList);
        vo.setCheckBys(checkBys);
        //定时任务默认关闭
        vo.setStatus(false);
        //设置定时任务辅助配置信息
        vo.setExcursionTime(RandomUtil.randomLong(12 * 1000 + 1) - 6 * 1000);
        Date actualStartTime = new Date(vo.getStartTime().getTime() + vo.getExcursionTime());
        vo.setActualStartTime(actualStartTime);
        vo.setNextActualStartTime(actualStartTime);

        if (vo.getId() == null) {
            //新增
            riskCheckTaskMapper.insert(vo);
            scheduleSettingService.addCheckTask(vo);
        } else {
            //修改
            riskCheckTaskMapper.updateById(vo);
            scheduleSettingService.updateCheckTask(vo);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean upStatus(Long id) throws IllegalAccessException {
        RiskCheckTask task = getById(id);
        boolean newStatus = !task.getStatus();//新状态
        task.setStatus(newStatus);
        ScheduleSetting scheduleSetting = scheduleSettingService.getOne(new LambdaQueryWrapper<ScheduleSetting>()
                .eq(ScheduleSetting::getRemark, String.valueOf(id)));
        //判断任务配置是否存在
        if (scheduleSetting != null) {
            //启动 并且 下一周期开始时间小于当前时间则重新计算下一周期开始时间
            if (newStatus && task.getNextActualStartTime().getTime() < System.currentTimeMillis()) {
                //计算离当前时间最近一条排查任务的开始时间
                Date lastBeginTime = taskFactory.getRecentBeginTime(
                        task.getCycleType(),
                        task.getNextActualStartTime(),
                        task.getCycle(),
                        task.getCycleUnit());
                task.setNextActualStartTime(lastBeginTime);
                scheduleSetting.setStatus(true);
                scheduleSettingService.update(scheduleSetting, true);
            } else {
                scheduleSettingService.changesStatus(scheduleSetting.getId(), newStatus);
            }
        } else {
            Date lastBeginTime = taskFactory.getRecentBeginTime(
                    task.getCycleType(),
                    task.getActualStartTime(),
                    task.getCycle(),
                    task.getCycleUnit());
            task.setNextActualStartTime(lastBeginTime);
            scheduleSettingService.addCheckTask(task, newStatus);
        }
        //修改排查任务
        riskCheckTaskMapper.updateById(task);
        //生成往期任务
        if (newStatus && task.getPreviousPeriodsNum() > 0) {
            checkRecordService.savePreviousPeriods(task);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id) {
        RiskCheckTask byId = getById(id);
        byId.setStatus(false);
        byId.setDelFlag("1");
        riskCheckTaskMapper.updateById(byId);
        //查询对应的定时任务配置
        ScheduleSetting scheduleSetting = scheduleSettingService.getOne(
                new LambdaQueryWrapper<ScheduleSetting>().eq(ScheduleSetting::getRemark, String.valueOf(id)));
        //删除定时任务
        if (scheduleSetting != null) {
            scheduleSettingService.del(scheduleSetting.getId());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> ids) {
        List<RiskCheckTask> tasks = list(new LambdaQueryWrapper<RiskCheckTask>().in(RiskCheckTask::getId, ids));
        tasks.forEach(task -> {
            task.setStatus(false);
            task.setDelFlag("1");
            riskCheckTaskMapper.updateById(task);
        });
        //查询对应的定时任务配置
        List<ScheduleSetting> scheduleSettings = scheduleSettingService.list(
                new LambdaQueryWrapper<ScheduleSetting>().in(ScheduleSetting::getRemark, ids));
        //删除定时任务
        if (!scheduleSettings.isEmpty()) {
            List<Long> list = scheduleSettings.stream().map(ScheduleSetting::getId).collect(Collectors.toList());
            scheduleSettingService.delByIds(list);
        }
        return true;
    }

}
